/******************************************************************************
 * * desktop_goto.c - implementation of goto functions
 *
 * *(C) Copyright 2019 Asr International Ltd.
 * * All Rights Reserved
 * ******************************************************************************/
#include "desktop_global.h"


/**
 * Handle direction key pressed on List control
 * param (in) Key_Val: UI_KEY_VALUE
 * return  VOID
 */
VOID Framework_Press_Direction_Key_On_List(UI_KEY_VALUE Key_Val)
{
    VOID           *Param;
    UI_List_Desc_t *List;

    switch (Key_Val)
    {
    case KEY_UP:
    case KEY_LEFT:
        Param = Nav_Get_Param(Nav_Get_Top());
        List = &(((UI_Normal_List_Only_Desc_t *)Param)->List);
        if (0 != List->Index)
        {
            List->Index--;
        }
        else
        {
            List->Index = List->ListButtonCnt - 1;
        }
        break;

    case KEY_DOWN:
    case KEY_RIGHT:
        Param = Nav_Get_Param(Nav_Get_Top());
        List = &(((UI_Normal_List_Only_Desc_t *)Param)->List);
        if ((List->ListButtonCnt - 1) != List->Index)
        {
            List->Index++;
        }
        else
        {
            List->Index = 0;
        }
        break;

    default:
        break;
    }
} /* Framework_Press_Direction_Key_On_List */


/**
 * Public callback function for destroying the interface with List control which will be popped from stack
 * param (in) Ctrl: VOID *
 * return  VOID
 */
VOID Framework_Normal_List_Interface_OnDestroy(VOID *Ctrl)
{
    Hal_Mem_Free(((UI_Normal_List_Only_Desc_t *)Ctrl)->List.ButtonList);
    Hal_Mem_Free(Ctrl);
}


/**
 * Action if timer expired for interface migration on Goto_Settings_Saved interface
 * param (in) VOID
 * return  VOID
 */
VOID Framework_Goto_Settings_Saved_Timeout(VOID* Para)
{
    g_FrameworkMng.TimerRunFlg = FALSE;

    Nav_Back(ACT_ID_GOTO_SETTINGS_SAVED);
}


/**
 * Start timer to keep Goto_Settings_Saved interface
 * param (in) VOID
 * return  VOID
 */
VOID Framework_Goto_Settings_Saved_Start_Timer(VOID)
{
    ACTIVITY_ID Para = ACT_ID_DIAL_MAIN;
    g_FrameworkMng.TimerId = Hal_Timer_Start(FRAMEWORK_TIMER_STATUS_INTERFACE_LENGTH, Framework_Goto_Settings_Saved_Timeout, (VOID *)&Para, FALSE);
    g_FrameworkMng.TimerRunFlg = TRUE;
}


/**
 * Callback function for additional actions after Creating Goto_Settings_Saved interface
 * param (in) Ctrl: VOID *
 * return  VOID
 */
VOID Framework_Goto_Settings_Saved_OnCreate(VOID *Ctrl)
{
    Framework_Goto_Settings_Saved_Start_Timer();
}


/**
 * Create Goto_Settings_Saved interface
 * param (in) VOID
 * return  VOID
 */
VOID Framework_Create_Goto_Settings_Saved(VOID)
{
    UI_Status_Desc_t *StatusDesc;
    Nav_Func_List_t  FuncList;

    StatusDesc = (UI_Status_Desc_t *)Hal_Mem_Alloc(sizeof(UI_Status_Desc_t));
    Hal_Mem_Set(StatusDesc, 0, sizeof(UI_Status_Desc_t));

    StatusDesc->ContLabel.TxtId      = PHONE_TEXT_ID_CHANGES_SAVED;
    StatusDesc->ContLabel.TxtAlign   = LV_LABEL_ALIGN_LEFT;
    StatusDesc->ContLabel.LabelAlign = LV_ALIGN_IN_TOP_LEFT;
    StatusDesc->ContLabelAlign       = LV_ALIGN_IN_TOP_LEFT;

    StatusDesc->ContImg.Img  = (VOID *)SYMBOL_CHECKED;
    StatusDesc->ContImgAlign = LV_ALIGN_IN_TOP_RIGHT;

    Hal_Mem_Set(&FuncList, 0, sizeof(Nav_Func_List_t));
    FuncList.OnShow      = UI_Status_Create;
    FuncList.OnCreate    = Framework_Goto_Settings_Saved_OnCreate;
    FuncList.OnSaveState = Framework_Interface_OnSaveState;
    FuncList.OnDestroy   = Framework_Interface_OnDestroy;

    Nav_Backward_And_Forward(ACT_ID_ANY,
                             ACT_ID_GOTO,
                             ACT_ID_GOTO_SETTINGS_SAVED,
                             &FuncList,
                             StatusDesc);
}


/**
 * Callback function for additional actions after Creating Goto_Settings_Options interface
 * param (in) Ctrl: VOID *
 * return  VOID
 */
VOID Framework_Goto_Settings_Options_OnCreate(VOID *Ctrl)
{
    UI_Button_Desc_t *BtnList = ((UI_Normal_List_Only_Desc_t *)Ctrl)->List.ButtonList;
    Framework_App_t  *App     = g_FrameworkMng.AppList;
    UINT8            i        = 0;

    while (NULL != App)
    {
        if (NULL == BtnList[i].Button)
        {
            /* error */
            return;
        }

        BtnList[i].Button->user_data.user_data = (VOID *)App;
        i++;
        App = App->Next;
    }
}


/**
 * Callback function for restoring state on Goto_Settings_Options interface after backward from another activity
 * param (in) Ctrl: VOID *
 * return  VOID
 */
VOID Framework_Goto_Settings_Options_OnRestoreState(VOID *Ctrl)
{
    UI_Button_Desc_t *BtnList = ((UI_Normal_List_Only_Desc_t *)Ctrl)->List.ButtonList;
    Framework_App_t  *App     = g_FrameworkMng.AppList;
    UINT8            i        = 0;

    while (NULL != App)
    {
        if (NULL == BtnList[i].Button)
        {
            /* error */
            return;
        }

        BtnList[i].Button->user_data.user_data = (VOID *)App;
        i++;
        App = App->Next;
    }
}


/**
 * Action if pressing APP button on Goto_Settings_Options interface
 * param (in) Btn: lv_obj_t *
 * param (in) Event: lv_event_t
 * return  VOID
 */
VOID Framework_Goto_Settings_Options_Btn_App_Cb(lv_obj_t *Btn, lv_event_t Event)
{
    if (LV_EVENT_CLICKED != Event)
    {
        return;
    }

    Framework_App_t *App   = (Framework_App_t *)Btn->user_data.user_data;
    lv_obj_t        *Label = lv_obj_get_child(Btn, NULL);
    lv_obj_t        *img   = lv_obj_get_child(Btn, Label);
    VOID            *Param = Nav_Get_Param(ACT_ID_GOTO_SETTINGS_OPTIONS);
    UI_List_Desc_t  *List  = &(((UI_Normal_List_Only_Desc_t *)Param)->List);
    UINT8           Index;

    if (NULL == img)
    {
        /* error */
        return;
    }

    Index = List->Index;

    if (0 == App->GotoIndex) // APP shortcut was unmarked
    {
        g_FrameworkMng.GotoAppNum++;
        App->GotoIndex  = g_FrameworkMng.GotoAppNum;
        App->GotoIndex |= 0x01 << 7; // change to be marked temporarily

        List->ButtonList[Index].SymbolId1 = SYMBOL_CHECKED;
        lv_img_set_src(img, SYMBOL_CHECKED);
    }
    else if (0 != (App->GotoIndex & (0x01 << 6))) // APP shortcut was unmarked temporarily
    {
        App->GotoIndex &= ~(0x01 << 6);           // change to be marked temporarily

        List->ButtonList[Index].SymbolId1 = SYMBOL_CHECKED;
        lv_img_set_src(img, SYMBOL_CHECKED);
    }
    else if (0 != (App->GotoIndex & (0x01 << 7))) // APP shortcut was marked temporarily
    {
        App->GotoIndex = 0;                       // change to be unmarked

        List->ButtonList[Index].SymbolId1 = SYMBOL_NOT_CHECKED;
        lv_img_set_src(img, SYMBOL_NOT_CHECKED);
    }
    else // APP shortcut was marked
    {
        App->GotoIndex |= 0x01 << 6; // change to unmarked temporarily

        List->ButtonList[Index].SymbolId1 = SYMBOL_NOT_CHECKED;
        lv_img_set_src(img, SYMBOL_NOT_CHECKED);
    }
} /* Framework_Goto_Settings_Options_Btn_App_Cb */


/**
 * Action if pressing option key on Goto_Settings_Options interface
 * param (in) VOID
 * return  VOID
 */
VOID Framework_Goto_Settings_Options_Press_Option_Key(VOID)
{
    UINT8                      i;
    Framework_App_t            *AppTemp = NULL;
    Framework_App_t            *AppList = g_FrameworkMng.AppList;
    NV_UI_Framework_t          Nvm;
    UINT8                      GotoIndex; // starts from 1
    UI_Normal_List_Only_Desc_t *NormalLstOnlyDesc
        = (UI_Normal_List_Only_Desc_t *)Nav_Get_Param(ACT_ID_GOTO);
    UINT32                     Len;

    g_FrameworkMng.GotoAppNum = 0;

    /* save the temporary changes */
    while (NULL != AppList)
    {
        if (0 != (AppList->GotoIndex & (0x01 << 6)))
        {   /* delete the APP shortcut from Go to list */
            AppList->GotoIndex = 0;
        }
        if (0 != (AppList->GotoIndex & (0x01 << 7)))
        {   /* add the APP shortcut into Go to list */
            AppList->GotoIndex &= ~(0x01 << 7);
        }
        if (0 != AppList->GotoIndex)
        {
            g_FrameworkMng.GotoAppNum++;
        }

        AppList = AppList->Next;
    }

    /* save as the continuous GotoIndex and write to NVM */
    Hal_Mem_Set(&Nvm, 0xFF, sizeof(NV_UI_Framework_t));
    for (i = 0; i < g_FrameworkMng.GotoAppNum; i++)
    {
        AppList   = g_FrameworkMng.AppList;
        GotoIndex = i + 1;
        while (NULL != AppList)
        {
            if (GotoIndex <= AppList->GotoIndex)
            {
                if (NULL == AppTemp)
                {
                    AppTemp = AppList;
                }
                else if (AppTemp->GotoIndex > AppList->GotoIndex)
                {
                    AppTemp = AppList;
                }
            }

            AppList = AppList->Next;
        }

        AppTemp->GotoIndex   = GotoIndex;
        Nvm.AppNameTextId[i] = AppTemp->NameTextId;
        AppTemp              = NULL;
    }

    UI_NV_Write_Req(NV_SECTION_UI_FRAMEWORK, 0, sizeof(NV_UI_Framework_t), (UINT8 *)(&Nvm));

    /* update description for Goto interface */
    Hal_Mem_Free(NormalLstOnlyDesc->List.ButtonList);
    NormalLstOnlyDesc->List.ListButtonCnt = g_FrameworkMng.GotoAppNum + 1;
    Len                                   = sizeof(UI_Button_Desc_t) *
                                            (g_FrameworkMng.GotoAppNum + 1);                            // APPs + settings
    NormalLstOnlyDesc->List.ButtonList = (UI_Button_Desc_t *)Hal_Mem_Alloc(Len);
    Hal_Mem_Set(NormalLstOnlyDesc->List.ButtonList, 0, Len);

    for (i = 0; i < g_FrameworkMng.GotoAppNum; i++)
    {
        AppList   = g_FrameworkMng.AppList;
        GotoIndex = i + 1;
        while (NULL != AppList)
        {
            if (GotoIndex == AppList->GotoIndex)
            {
                NormalLstOnlyDesc->List.ButtonList[i].Valid       = TRUE;
                NormalLstOnlyDesc->List.ButtonList[i].ButtonIndex = i;
                NormalLstOnlyDesc->List.ButtonList[i].TxtId       = AppList->NameTextId;
                NormalLstOnlyDesc->List.ButtonList[i].ReleaseFun  = Framework_Goto_Btn_App_Cb;
                break;
            }
            else
            {
                AppList = AppList->Next;
            }
        }
    }
    NormalLstOnlyDesc->List.ButtonList[i].Valid       = TRUE;
    NormalLstOnlyDesc->List.ButtonList[i].ButtonIndex = i;
    NormalLstOnlyDesc->List.ButtonList[i].TxtId       = PHONE_TEXT_ID_GOTO_SETTINGS;
    NormalLstOnlyDesc->List.ButtonList[i].ReleaseFun  = Framework_Goto_Btn_Go_to_Settings_Cb;
    NormalLstOnlyDesc->List.Index                     = 0;
} /* Goto_Settings_Press_Option_Key */


/**
 * Action if pressing back key on Goto_Settings_Options interface
 * param (in) VOID
 * return  VOID
 */
VOID Framework_Goto_Settings_Options_Press_Back_Key(VOID)
{
    Framework_App_t *AppList = g_FrameworkMng.AppList;

    /* clear the temporary changes */
    while (NULL != AppList)
    {
        if (0 != (AppList->GotoIndex & (0x01 << 6)))
        {
            AppList->GotoIndex &= ~(0x01 << 6);
        }
        if (0 != (AppList->GotoIndex & (0x01 << 7)))
        {
            AppList->GotoIndex &= ~(0x01 << 7);
        }

        AppList = AppList->Next;
    }
}


/**
 * Callback function for handling key pressed on Goto_Settings_Options interface
 * param (in) Obj: lv_obj_t *
 * param (in) Key_Sta: UI_KEY_STATUS
 * param (in) Key_Val: UI_KEY_VALUE
 * return  UINT8
 */
UINT8 Framework_Goto_Settings_Options_Key_Cb(lv_obj_t *Obj, UI_KEY_STATUS Key_Sta,
    UI_KEY_VALUE Key_Val)
{
    UINT8 Ret = 1; // not call default key function for List

    if (KEY_RELEASED == Key_Sta)
    {
        switch (Key_Val)
        {
        case KEY_SOFTLEFT: // save changes
            Framework_Goto_Settings_Options_Press_Option_Key();
            Framework_Create_Goto_Settings_Saved();
            break;

        case KEY_SOFTRIGHT: // not save changes
            Framework_Goto_Settings_Options_Press_Back_Key();
            Nav_Back(ACT_ID_ANY);
            break;

        case KEY_END: // not save changes
            Framework_Goto_Settings_Options_Press_Back_Key();
            Nav_Home(ACT_ID_ANY);
            break;

        case KEY_OK:
        case KEY_UP:
        case KEY_DOWN:
        case KEY_LEFT:
        case KEY_RIGHT:
            Framework_Press_Direction_Key_On_List(Key_Val);
            Ret = 0; // call default key function for List
            break;

        default:
            break;
        } /* switch */
    }

    return(Ret);
}


/**
 * Create Goto_Settings_Options interface
 * param (in) VOID
 * return  VOID
 */
VOID Framework_Create_Goto_Settings_Options(VOID)
{
    UI_Normal_List_Only_Desc_t *NormalLstOnlyDesc;
    Nav_Func_List_t            FuncList;
    Framework_App_t            *App;
    UINT32                     Len;
    UINT8                      i = 0;

    NormalLstOnlyDesc =
        (UI_Normal_List_Only_Desc_t *)Hal_Mem_Alloc(sizeof(UI_Normal_List_Only_Desc_t));
    Hal_Mem_Set(NormalLstOnlyDesc, 0, sizeof(UI_Normal_List_Only_Desc_t));

    NormalLstOnlyDesc->TitleBar.TxtId      = PHONE_TEXT_ID_SELECT_OPT;
    NormalLstOnlyDesc->TitleBar.TxtAlign   = LV_LABEL_ALIGN_CENTER;
    NormalLstOnlyDesc->TitleBar.LabelAlign = LV_ALIGN_IN_TOP_LEFT;

    App = g_FrameworkMng.AppList;
    while (NULL != App)
    {
        NormalLstOnlyDesc->List.ListButtonCnt++;
        App = App->Next;
    }
    Len = sizeof(UI_Button_Desc_t) *
          NormalLstOnlyDesc->List.ListButtonCnt;
    NormalLstOnlyDesc->List.ButtonList = (UI_Button_Desc_t *)Hal_Mem_Alloc(Len);
    Hal_Mem_Set(NormalLstOnlyDesc->List.ButtonList, 0, Len);
    App = g_FrameworkMng.AppList;
    while (NULL != App)
    {
        NormalLstOnlyDesc->List.ButtonList[i].Valid = TRUE;
        NormalLstOnlyDesc->List.ButtonList[i].TxtId = App->NameTextId;
        if (0 != App->GotoIndex) // APP in Go to list
        {
            NormalLstOnlyDesc->List.ButtonList[i].SymbolId1 = SYMBOL_CHECKED;
        }
        else
        {
            NormalLstOnlyDesc->List.ButtonList[i].SymbolId1 = SYMBOL_NOT_CHECKED;
        }
        NormalLstOnlyDesc->List.ButtonList[i].ReleaseFun =
            Framework_Goto_Settings_Options_Btn_App_Cb;
        i++;

        App = App->Next;
    }

    NormalLstOnlyDesc->BtnBar.ButtonL.Valid = TRUE;
    NormalLstOnlyDesc->BtnBar.ButtonL.TxtId = PHONE_TEXT_ID_SAVE;
    NormalLstOnlyDesc->BtnBar.ButtonM.Valid = TRUE;
    NormalLstOnlyDesc->BtnBar.ButtonM.TxtId = PHONE_TEXT_ID_SELECT;
    NormalLstOnlyDesc->BtnBar.ButtonR.Valid = TRUE;
    NormalLstOnlyDesc->BtnBar.ButtonR.TxtId = PHONE_TEXT_ID_BACK;
    NormalLstOnlyDesc->KeyFunc              = Framework_Goto_Settings_Options_Key_Cb;

    Hal_Mem_Set(&FuncList, 0, sizeof(Nav_Func_List_t));
    FuncList.OnShow         = UI_Normal_List_Only_Create;
    FuncList.OnCreate       = Framework_Goto_Settings_Options_OnCreate;
    FuncList.OnRestoreState = Framework_Goto_Settings_Options_OnRestoreState;
    FuncList.OnDestroy      = Framework_Normal_List_Interface_OnDestroy;

    Nav_Forward(ACT_ID_ANY, ACT_ID_GOTO_SETTINGS_OPTIONS, &FuncList, NormalLstOnlyDesc);
} /* Framework_Create_Goto_Settings_Options */


/**
 * Callback function for additional actions after Creating Goto_Settings_Move interface
 * param (in) Ctrl: VOID *
 * return  VOID
 */
VOID Framework_Goto_Settings_Move_OnCreate(VOID *Ctrl)
{
    UI_Button_Desc_t *ButtonList = ((UI_Normal_List_Only_Desc_t *)Ctrl)->List.ButtonList;
    Framework_App_t  *App;
    UINT8            i;

    for (i = 0; i < g_FrameworkMng.GotoAppNum; i++)
    {
        App = g_FrameworkMng.AppList;

        while (NULL != App)
        {
            if (ButtonList[i].TxtId == App->NameTextId)
            {
                ButtonList[i].Button->user_data.user_data = (VOID *)App;
                break;
            }
            else
            {
                App = App->Next;
            }
        }
    }
}


/**
 * Callback function for restoring state on Goto_Settings_Move interface after backward from another activity
 * param (in) Ctrl: VOID *
 * return  VOID
 */
VOID Framework_Goto_Settings_Move_OnRestoreState(VOID *Ctrl)
{
    UI_Button_Desc_t *ButtonList = ((UI_Normal_List_Only_Desc_t *)Ctrl)->List.ButtonList;
    Framework_App_t  *App;
    UINT8            i;

    for (i = 0; i < g_FrameworkMng.GotoAppNum; i++)
    {
        App = g_FrameworkMng.AppList;

        while (NULL != App)
        {
            if (ButtonList[i].TxtId == App->NameTextId)
            {
                ButtonList[i].Button->user_data.user_data = (VOID *)App;
                break;
            }
            else
            {
                App = App->Next;
            }
        }
    }
}


/**
 * Move the current APP shortcut up in APP shortcut list on Goto_Settings_Move interface
 * param (in) VOID
 * return  VOID
 */
VOID Framework_Goto_Settings_Move_Up(VOID)
{
    VOID                       *Param = Nav_Get_Param(ACT_ID_GOTO_SETTINGS_MOVE);
    UI_List_Desc_t             *List = &(((UI_Normal_List_Only_Desc_t *)Param)->List);
    lv_obj_t                   *CurBtn;
    lv_obj_t                   *PrevBtn;
    UI_Button_Desc_t           TempBtn;
    Framework_App_t            *CurApp;
    Framework_App_t            *PrevApp;
    UINT16                     AppNameTextId[2]; // for NVM
    UINT32                     Len;
    UINT32                     OffSet;
    UI_Normal_List_Only_Desc_t *NormalLstOnlyDesc =
        (UI_Normal_List_Only_Desc_t *)Nav_Get_Param(ACT_ID_GOTO);

    if (0 == List->Index)
    {   /* APP shortcut has been in the top of list */
        return;
    }

    CurBtn  = List->ButtonList[List->Index].Button;
    PrevBtn = List->ButtonList[List->Index - 1].Button;

    CurApp  = (Framework_App_t *)CurBtn->user_data.user_data;
    PrevApp = (Framework_App_t *)PrevBtn->user_data.user_data;

    Hal_Mem_Copy(&TempBtn, &List->ButtonList[List->Index], sizeof(UI_Button_Desc_t));
    Hal_Mem_Copy(&List->ButtonList[List->Index], &List->ButtonList[List->Index - 1],
        sizeof(UI_Button_Desc_t));
    Hal_Mem_Copy(&List->ButtonList[List->Index - 1], &TempBtn, sizeof(UI_Button_Desc_t));

    /* update description for Goto interface */
    Hal_Mem_Copy(&TempBtn, &NormalLstOnlyDesc->List.ButtonList[List->Index],
        sizeof(UI_Button_Desc_t));
    Hal_Mem_Copy(&NormalLstOnlyDesc->List.ButtonList[List->Index],
        &NormalLstOnlyDesc->List.ButtonList[List->Index - 1], sizeof(UI_Button_Desc_t));
    Hal_Mem_Copy(&NormalLstOnlyDesc->List.ButtonList[List->Index - 1], &TempBtn,
        sizeof(UI_Button_Desc_t));
    NormalLstOnlyDesc->List.Index = 0;

    List->ButtonList[List->Index].Button     = CurBtn;
    List->ButtonList[List->Index - 1].Button = PrevBtn;

    CurBtn->user_data.user_data  = (VOID *)PrevApp;
    PrevBtn->user_data.user_data = (VOID *)CurApp;

    lv_label_set_text(lv_obj_get_child(PrevBtn, NULL), lv_lang_get_text(CurApp->NameTextId));
    CurApp->GotoIndex--;
    AppNameTextId[0] = CurApp->NameTextId;

    lv_label_set_text(lv_obj_get_child(CurBtn, NULL), lv_lang_get_text(PrevApp->NameTextId));
    PrevApp->GotoIndex++;
    AppNameTextId[1] = PrevApp->NameTextId;

    lv_list_focus_btn(List->List, PrevBtn);
    lv_list_focus(PrevBtn, FALSE);
    List->Index--;

    OffSet = List->Index * sizeof(UINT16);
    Len    = sizeof(UINT16) * 2;
    UI_NV_Write_Req(NV_SECTION_UI_FRAMEWORK, OffSet, Len, (UINT8 *)AppNameTextId);
} /* Framework_Goto_Settings_Move_Up */


/**
 * Move the current APP shortcut down in APP shortcut list on Goto_Settings_Move interface
 * param (in) VOID
 * return  VOID
 */
VOID Framework_Goto_Settings_Move_Down(VOID)
{
    VOID                       *Param = Nav_Get_Param(ACT_ID_GOTO_SETTINGS_MOVE);
    UI_List_Desc_t             *List = &(((UI_Normal_List_Only_Desc_t *)Param)->List);
    lv_obj_t                   *CurBtn;
    lv_obj_t                   *NextBtn;
    UI_Button_Desc_t           TempBtn;
    Framework_App_t            *CurApp;
    Framework_App_t            *NextApp;
    UINT16                     AppNameTextId[2]; // for NVM
    UINT32                     Len;
    UINT32                     OffSet;
    UI_Normal_List_Only_Desc_t *NormalLstOnlyDesc =
        (UI_Normal_List_Only_Desc_t *)Nav_Get_Param(ACT_ID_GOTO);

    if ((List->ListButtonCnt - 1) == List->Index)
    {   /* APP shortcut has been in the bottom of list */
        return;
    }

    CurBtn  = List->ButtonList[List->Index].Button;
    NextBtn = List->ButtonList[List->Index + 1].Button;

    CurApp  = (Framework_App_t *)CurBtn->user_data.user_data;
    NextApp = (Framework_App_t *)NextBtn->user_data.user_data;

    Hal_Mem_Copy(&TempBtn, &List->ButtonList[List->Index], sizeof(UI_Button_Desc_t));
    Hal_Mem_Copy(&List->ButtonList[List->Index], &List->ButtonList[List->Index + 1],
        sizeof(UI_Button_Desc_t));
    Hal_Mem_Copy(&List->ButtonList[List->Index + 1], &TempBtn, sizeof(UI_Button_Desc_t));

    /* update description for Goto interface */
    Hal_Mem_Copy(&TempBtn, &NormalLstOnlyDesc->List.ButtonList[List->Index],
        sizeof(UI_Button_Desc_t));
    Hal_Mem_Copy(&NormalLstOnlyDesc->List.ButtonList[List->Index],
        &NormalLstOnlyDesc->List.ButtonList[List->Index + 1], sizeof(UI_Button_Desc_t));
    Hal_Mem_Copy(&NormalLstOnlyDesc->List.ButtonList[List->Index + 1], &TempBtn,
        sizeof(UI_Button_Desc_t));
    NormalLstOnlyDesc->List.Index = 0;

    List->ButtonList[List->Index].Button     = CurBtn;
    List->ButtonList[List->Index + 1].Button = NextBtn;

    CurBtn->user_data.user_data  = (VOID *)NextApp;
    NextBtn->user_data.user_data = (VOID *)CurApp;

    lv_label_set_text(lv_obj_get_child(CurBtn, NULL), lv_lang_get_text(NextApp->NameTextId));
    NextApp->GotoIndex--;
    AppNameTextId[0] = NextApp->NameTextId;

    lv_label_set_text(lv_obj_get_child(NextBtn, NULL), lv_lang_get_text(CurApp->NameTextId));
    CurApp->GotoIndex++;
    AppNameTextId[1] = CurApp->NameTextId;

    lv_list_focus_btn(List->List, NextBtn);
    lv_list_focus(NextBtn, FALSE);

    OffSet = List->Index * sizeof(UINT16);
    Len    = sizeof(UINT16) * 2;
    UI_NV_Write_Req(NV_SECTION_UI_FRAMEWORK, OffSet, Len, (UINT8 *)AppNameTextId);

    List->Index++;
} /* Framework_Goto_Settings_Move_Down */


/**
 * Callback function for handling key pressed on Goto_Settings_Move interface
 * param (in) Obj: lv_obj_t *
 * param (in) Key_Sta: UI_KEY_STATUS
 * param (in) Key_Val: UI_KEY_VALUE
 * return  UINT8
 */
UINT8 Framework_Goto_Settings_Move_Key_Cb(lv_obj_t *Obj, UI_KEY_STATUS Key_Sta,
    UI_KEY_VALUE Key_Val)
{
    UINT8 Ret = 1; // not call default key function for List

    if (KEY_RELEASED == Key_Sta)
    {
        switch (Key_Val)
        {
        case KEY_SOFTRIGHT:
            Nav_Back(ACT_ID_ANY);
            break;

        case KEY_END:
            Nav_Home(ACT_ID_ANY);
            break;

        case KEY_SOFTLEFT: // move up
            Framework_Goto_Settings_Move_Up();
            break;

        case KEY_OK: // move down
            Framework_Goto_Settings_Move_Down();
            break;

        case KEY_UP:
        case KEY_DOWN:
        case KEY_LEFT:
        case KEY_RIGHT:
            Framework_Press_Direction_Key_On_List(Key_Val);
            Ret = 0; // call default key function for List
            break;

        default:
            break;
        } /* switch */
    }

    return(Ret);
}


/**
 * Create Goto_Settings_Move interface
 * param (in) VOID
 * return  VOID
 */
VOID Framework_Create_Goto_Settings_Move(VOID)
{
    UI_Normal_List_Only_Desc_t *NormalLstOnlyDesc;
    Nav_Func_List_t            FuncList;
    UINT32                     Len;
    Framework_App_t            *AppList;
    UINT8                      i;
    UINT8                      GotoIndex; // starting from 1

    NormalLstOnlyDesc =
        (UI_Normal_List_Only_Desc_t *)Hal_Mem_Alloc(sizeof(UI_Normal_List_Only_Desc_t));
    Hal_Mem_Set(NormalLstOnlyDesc, 0, sizeof(UI_Normal_List_Only_Desc_t));

    NormalLstOnlyDesc->TitleBar.TxtId      = PHONE_TEXT_ID_ORGANISE;
    NormalLstOnlyDesc->TitleBar.TxtAlign   = LV_LABEL_ALIGN_CENTER;
    NormalLstOnlyDesc->TitleBar.LabelAlign = LV_ALIGN_IN_TOP_LEFT;

    NormalLstOnlyDesc->List.ListButtonCnt = g_FrameworkMng.GotoAppNum;
    Len                                   = sizeof(UI_Button_Desc_t) * g_FrameworkMng.GotoAppNum;
    NormalLstOnlyDesc->List.ButtonList    = (UI_Button_Desc_t *)Hal_Mem_Alloc(Len);
    Hal_Mem_Set(NormalLstOnlyDesc->List.ButtonList, 0, Len);
    for (i = 0; i < g_FrameworkMng.GotoAppNum; i++)
    {
        AppList   = g_FrameworkMng.AppList;
        GotoIndex = i + 1;
        while (NULL != AppList)
        {
            if (GotoIndex == AppList->GotoIndex)
            {
                NormalLstOnlyDesc->List.ButtonList[i].Valid       = TRUE;
                NormalLstOnlyDesc->List.ButtonList[i].ButtonIndex = i;
                NormalLstOnlyDesc->List.ButtonList[i].TxtId       = AppList->NameTextId;
                break;
            }
            else
            {
                AppList = AppList->Next;
            }
        }
    }

    NormalLstOnlyDesc->BtnBar.ButtonL.Valid = TRUE;
    NormalLstOnlyDesc->BtnBar.ButtonL.TxtId = PHONE_TEXT_ID_UP;
    NormalLstOnlyDesc->BtnBar.ButtonM.Valid = TRUE;
    NormalLstOnlyDesc->BtnBar.ButtonM.TxtId = PHONE_TEXT_ID_DOWN;
    NormalLstOnlyDesc->BtnBar.ButtonR.Valid = TRUE;
    NormalLstOnlyDesc->BtnBar.ButtonR.TxtId = PHONE_TEXT_ID_BACK;

    NormalLstOnlyDesc->KeyFunc = Framework_Goto_Settings_Move_Key_Cb;

    Hal_Mem_Set(&FuncList, 0, sizeof(Nav_Func_List_t));
    FuncList.OnShow         = UI_Normal_List_Only_Create;
    FuncList.OnCreate       = Framework_Goto_Settings_Move_OnCreate;
    FuncList.OnRestoreState = Framework_Goto_Settings_Move_OnRestoreState;
    FuncList.OnSaveState    = Framework_Interface_OnSaveState;
    FuncList.OnDestroy      = Framework_Interface_OnDestroy;

    Nav_Forward(ACT_ID_ANY, ACT_ID_GOTO_SETTINGS_MOVE, &FuncList, NormalLstOnlyDesc);
} /* Framework_Create_Goto_Settings_Move */


/**
 * Action if pressing select options button on Goto_Settings interface
 * param (in) Btn: lv_obj_t *
 * param (in) Event: lv_event_t
 * return  VOID
 */
VOID Framework_Goto_Settings_Btn_Select_Options_Cb(lv_obj_t *Btn, lv_event_t Event)
{
    if (LV_EVENT_CLICKED != Event)
    {
        return;
    }

    UI_Log_Out(UI_SUB_MODULE_FRAMEWORK, UI_LOG_LEVEL_TRACE_1,
        "Framework_Goto_Settings_Btn_Select_Options_Cb\n");

    Framework_Create_Goto_Settings_Options();
}


/**
 * Action if pressing move button on Goto_Settings interface
 * param (in) Btn: lv_obj_t *
 * param (in) Event: lv_event_t
 * return  VOID
 */
VOID Framework_Goto_Settings_Btn_Move_Cb(lv_obj_t *Btn, lv_event_t Event)
{
    if (LV_EVENT_CLICKED != Event)
    {
        return;
    }

    Framework_Create_Goto_Settings_Move();
}


/**
 * Callback function for handling key pressed on Goto_Settings interface
 * param (in) Obj: lv_obj_t *
 * param (in) Key_Sta: UI_KEY_STATUS
 * param (in) Key_Val: UI_KEY_VALUE
 * return  UINT8
 */
UINT8 Framework_Goto_Settings_Key_Cb(lv_obj_t *Obj, UI_KEY_STATUS Key_Sta, UI_KEY_VALUE Key_Val)
{
    UINT8 Ret = 1; // not call default key function for List

    if (KEY_RELEASED == Key_Sta)
    {
        switch (Key_Val)
        {
        case KEY_SOFTRIGHT:
            Nav_Back(ACT_ID_ANY);
            break;

        case KEY_END:
            Nav_Home(ACT_ID_ANY);
            break;

        case KEY_OK:
        case KEY_UP:
        case KEY_DOWN:
        case KEY_LEFT:
        case KEY_RIGHT:
            Framework_Press_Direction_Key_On_List(Key_Val);
            Ret = 0; // call default key function for List
            break;

        default:
            break;
        } /* switch */
    }

    return(Ret);
}


/**
 * Create Goto_Settings interface
 * param (in) VOID
 * return  VOID
 */
VOID Framework_Create_Goto_Settings(VOID)
{
    UI_Normal_List_Only_Desc_t *NormalLstOnlyDesc;
    Nav_Func_List_t            FuncList;
    UINT32                     Len;

    NormalLstOnlyDesc =
        (UI_Normal_List_Only_Desc_t *)Hal_Mem_Alloc(sizeof(UI_Normal_List_Only_Desc_t));
    Hal_Mem_Set(NormalLstOnlyDesc, 0, sizeof(UI_Normal_List_Only_Desc_t));

    NormalLstOnlyDesc->TitleBar.TxtId      = PHONE_TEXT_ID_GOTO_SETTINGS;
    NormalLstOnlyDesc->TitleBar.TxtAlign   = LV_LABEL_ALIGN_CENTER;
    NormalLstOnlyDesc->TitleBar.LabelAlign = LV_ALIGN_IN_TOP_LEFT;

    if (0 != g_FrameworkMng.GotoAppNum)
    {
        NormalLstOnlyDesc->List.ListButtonCnt = 2;
    }
    else
    {
        NormalLstOnlyDesc->List.ListButtonCnt = 1;
    }
    Len = sizeof(UI_Button_Desc_t) *
          NormalLstOnlyDesc->List.ListButtonCnt;
    NormalLstOnlyDesc->List.ButtonList = (UI_Button_Desc_t *)Hal_Mem_Alloc(Len);
    Hal_Mem_Set(NormalLstOnlyDesc->List.ButtonList, 0, Len);
    NormalLstOnlyDesc->List.ButtonList[0].Valid       = TRUE;
    NormalLstOnlyDesc->List.ButtonList[0].ButtonIndex = 0;
    NormalLstOnlyDesc->List.ButtonList[0].TxtId       = PHONE_TEXT_ID_SELECT_OPT;
    NormalLstOnlyDesc->List.ButtonList[0].ReleaseFun  =
        Framework_Goto_Settings_Btn_Select_Options_Cb;
    if (0 != g_FrameworkMng.GotoAppNum)
    {
        NormalLstOnlyDesc->List.ButtonList[1].Valid       = TRUE;
        NormalLstOnlyDesc->List.ButtonList[1].ButtonIndex = 1;
        NormalLstOnlyDesc->List.ButtonList[1].TxtId       = PHONE_TEXT_ID_ORGANISE;
        NormalLstOnlyDesc->List.ButtonList[1].ReleaseFun  = Framework_Goto_Settings_Btn_Move_Cb;
    }

    NormalLstOnlyDesc->BtnBar.ButtonL.Valid = FALSE;
    NormalLstOnlyDesc->BtnBar.ButtonM.Valid = TRUE;
    NormalLstOnlyDesc->BtnBar.ButtonM.TxtId = PHONE_TEXT_ID_SELECT;
    NormalLstOnlyDesc->BtnBar.ButtonR.Valid = TRUE;
    NormalLstOnlyDesc->BtnBar.ButtonR.TxtId = PHONE_TEXT_ID_BACK;

    NormalLstOnlyDesc->KeyFunc = Framework_Goto_Settings_Key_Cb;

    Hal_Mem_Set(&FuncList, 0, sizeof(Nav_Func_List_t));
    FuncList.OnShow      = UI_Normal_List_Only_Create;
    FuncList.OnSaveState = Framework_Interface_OnSaveState;
    FuncList.OnDestroy   = Framework_Normal_List_Interface_OnDestroy;

    Nav_Forward(ACT_ID_ANY, ACT_ID_GOTO_SETTINGS, &FuncList, NormalLstOnlyDesc);
} /* Framework_Create_Goto_Settings */


/**
 * Action if pressing go to settings button on Goto interface
 * param (in) Btn: lv_obj_t *
 * param (in) Event: lv_event_t
 * return  VOID
 */
VOID Framework_Goto_Btn_Go_to_Settings_Cb(lv_obj_t *Btn, lv_event_t Event)
{
    if (LV_EVENT_CLICKED != Event)
    {
        return;
    }

    Framework_Create_Goto_Settings();
}


/**
 * Action if pressing APP button on Goto interface
 * param (in) Btn: lv_obj_t *
 * param (in) Event: lv_event_t
 * return  VOID
 */
VOID Framework_Goto_Btn_App_Cb(lv_obj_t *Btn, lv_event_t Event)
{
    if (LV_EVENT_CLICKED != Event)
    {
        return;
    }

    Framework_App_t *App = (Framework_App_t *)Btn->user_data.user_data;

    App->AppFunc();
}


/**
 * Callback function for handling key pressed on Goto interface
 * param (in) Obj: lv_obj_t *
 * param (in) Key_Sta: UI_KEY_STATUS
 * param (in) Key_Val: UI_KEY_VALUE
 * return  UINT8
 */
UINT8 Framework_Goto_Key_Cb(lv_obj_t *Obj, UI_KEY_STATUS Key_Sta, UI_KEY_VALUE Key_Val)
{
    UINT8 Ret = 1; // not call default key function for List

    if (KEY_RELEASED == Key_Sta)
    {
        switch (Key_Val)
        {
        case KEY_SOFTRIGHT:
        case KEY_END:
            Nav_Back(ACT_ID_ANY);
            break;

        case KEY_OK:
        case KEY_UP:
        case KEY_DOWN:
        case KEY_LEFT:
        case KEY_RIGHT:
            Framework_Press_Direction_Key_On_List(Key_Val);
            Ret = 0; // call default key function for List
            break;

        default:
            break;
        } /* switch */
    }

    return(Ret);
}


/**
 * Callback function for additional actions after Creating Goto interface
 * param (in) Ctrl: VOID *
 * return  VOID
 */
VOID Framework_Goto_OnCreate(VOID *Ctrl)
{
    UI_Button_Desc_t *ButtonList = ((UI_Normal_List_Only_Desc_t *)Ctrl)->List.ButtonList;
    Framework_App_t  *App;
    UINT8            i;

    for (i = 0; i < g_FrameworkMng.GotoAppNum; i++)
    {
        App = g_FrameworkMng.AppList;

        while (NULL != App)
        {
            if (ButtonList[i].TxtId == App->NameTextId)
            {
                ButtonList[i].Button->user_data.user_data = (VOID *)App;
                break;
            }
            else
            {
                App = App->Next;
            }
        }
    }
}


/**
 * Callback function for restoring state on Goto interface after backward from another activity
 * param (in) Ctrl: VOID *
 * return  VOID
 */
VOID Framework_Goto_OnRestoreState(VOID *Ctrl)
{
    UI_Button_Desc_t *ButtonList = ((UI_Normal_List_Only_Desc_t *)Ctrl)->List.ButtonList;
    Framework_App_t  *App;
    UINT8            i;

    for (i = 0; i < g_FrameworkMng.GotoAppNum; i++)
    {
        App = g_FrameworkMng.AppList;

        while (NULL != App)
        {
            if (ButtonList[i].TxtId == App->NameTextId)
            {
                ButtonList[i].Button->user_data.user_data = (VOID *)App;
                break;
            }
            else
            {
                App = App->Next;
            }
        }
    }
}


/**
 * Create Goto interface
 * param (in) VOID
 * return  VOID
 */
VOID Framework_Create_Goto(VOID)
{
    Nav_Func_List_t            FuncList;
    UI_Normal_List_Only_Desc_t *NormalLstOnlyDesc;
    UINT32                     Len;
    Framework_App_t            *AppList;
    UINT8                      i;
    UINT8                      GotoIndex; // starting from 1

    NormalLstOnlyDesc =
        (UI_Normal_List_Only_Desc_t *)Hal_Mem_Alloc(sizeof(UI_Normal_List_Only_Desc_t));
    Hal_Mem_Set(NormalLstOnlyDesc, 0, sizeof(UI_Normal_List_Only_Desc_t));

    NormalLstOnlyDesc->TitleBar.TxtId      = PHONE_TEXT_ID_GOTO;
    NormalLstOnlyDesc->TitleBar.TxtAlign   = LV_LABEL_ALIGN_CENTER;
    NormalLstOnlyDesc->TitleBar.LabelAlign = LV_ALIGN_IN_TOP_LEFT;

    NormalLstOnlyDesc->List.ListButtonCnt = g_FrameworkMng.GotoAppNum + 1;
    Len                                   = sizeof(UI_Button_Desc_t) *
                                            (g_FrameworkMng.GotoAppNum + 1);                            // APPs + settings
    NormalLstOnlyDesc->List.ButtonList = (UI_Button_Desc_t *)Hal_Mem_Alloc(Len);
    Hal_Mem_Set(NormalLstOnlyDesc->List.ButtonList, 0, Len);

    for (i = 0; i < g_FrameworkMng.GotoAppNum; i++)
    {
        AppList   = g_FrameworkMng.AppList;
        GotoIndex = i + 1;
        while (NULL != AppList)
        {
            if (GotoIndex == AppList->GotoIndex)
            {
                NormalLstOnlyDesc->List.ButtonList[i].Valid       = TRUE;
                NormalLstOnlyDesc->List.ButtonList[i].ButtonIndex = i;
                NormalLstOnlyDesc->List.ButtonList[i].TxtId       = AppList->NameTextId;
                NormalLstOnlyDesc->List.ButtonList[i].ReleaseFun  = Framework_Goto_Btn_App_Cb;
                break;
            }
            else
            {
                AppList = AppList->Next;
            }
        }
    }
    NormalLstOnlyDesc->List.ButtonList[i].Valid       = TRUE;
    NormalLstOnlyDesc->List.ButtonList[i].ButtonIndex = i;
    NormalLstOnlyDesc->List.ButtonList[i].TxtId       = PHONE_TEXT_ID_GOTO_SETTINGS;
    NormalLstOnlyDesc->List.ButtonList[i].ReleaseFun  = Framework_Goto_Btn_Go_to_Settings_Cb;

    NormalLstOnlyDesc->BtnBar.ButtonL.Valid = FALSE;
    NormalLstOnlyDesc->BtnBar.ButtonM.Valid = TRUE;
    NormalLstOnlyDesc->BtnBar.ButtonM.TxtId = PHONE_TEXT_ID_SELECT;
    NormalLstOnlyDesc->BtnBar.ButtonR.Valid = TRUE;
    NormalLstOnlyDesc->BtnBar.ButtonR.TxtId = PHONE_TEXT_ID_BACK;

    NormalLstOnlyDesc->KeyFunc = Framework_Goto_Key_Cb;

    Hal_Mem_Set(&FuncList, 0, sizeof(Nav_Func_List_t));
    FuncList.OnShow         = UI_Normal_List_Only_Create;
    FuncList.OnCreate       = Framework_Goto_OnCreate;
    FuncList.OnRestoreState = Framework_Goto_OnRestoreState;
    FuncList.OnDestroy      = Framework_Normal_List_Interface_OnDestroy;

    Nav_Forward(ACT_ID_ANY, ACT_ID_GOTO, &FuncList, NormalLstOnlyDesc);
} /* Framework_Create_Goto */
